STM32F407通过SPI+DMA的方式驱动WS2812

您所在的位置:网站首页 stm32f407dma 串口与spi STM32F407通过SPI+DMA的方式驱动WS2812

STM32F407通过SPI+DMA的方式驱动WS2812

#STM32F407通过SPI+DMA的方式驱动WS2812| 来源: 网络整理| 查看: 265

关于STM32F407通过SPI+DMA的方式驱动WS2812的讲解与驱动demo

ws2812简介

1、控制电路与RGB芯片集成在一个5050封装的元器件中, 构成一个完整的外控像素点。 2、每个像素点的三基色颜色可实现256级亮度显示, 完成16777216种颜色的全真色彩显示, 扫描频率不低于400Hz/s。 3、串行级联接口, 能通过一根信号线完成数据的接收与解码。 4、任意两点传传输距离在不超过5米时无需增加任何电路。 5、当刷新速率30帧/秒时, 低速模式级联数不小于512点, 高速模式不小于1024点。 6、数据发送速度可达800Kbps。 7、光的颜色高度一致, 性价比高。 ws2812这款灯珠使用起来真的很方便,可以变换很多种颜色。但是,区分度较为明显的颜色不是很多,很多的颜色通过灯珠表现出来后辨识度不高。一般只能用红、橙、黄、绿、蓝、靛、紫、白和洋红这几种辨识度比较高的颜色。 LED的参数特性如下: LED参数

ws2812驱动原理

ws2812数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。 所谓的单线归零码,也称为单极性归零码,是指高电平和零电平分别表示二进制码1 和0,在无电压表示“0”,恒定正电压表示“1”,但持续时间短于一个码元的时间宽度,即发出一个窄脉冲。每个码元时间的中间点是采样时间,判决门限为半幅电平。 单极性归零码的主要优点是可以直接提取同步信号,因此单极性归零码常常用作其他码型提取同步信号时的过渡码型.也就是说其他适合信道传输但不能直接提取同步信号的码型,可先变换为单极性归零码,然后再提取同步信号。 它的具体体现如下图所示: 单极性归零码 看了上面关于单线归零码的介绍,再来看ws2812的驱动原理,就能一眼看懂了,ws2812主要就是靠发送0码和1码来控制颜色。 ws2812的控制原理为通过一定的时序,发送高低电平,其时序波形要求如下:

时序波形图 ws2812的码型时序要求: 时序 而这个led的驱动难点也在发送归零码上面,因为它有一个时序的要求,必须要满足它本身的时序才行。看了上面图形的介绍,可以看到信号的周期为1.25us,与前面的800kbps的通信频率正好对应。0码与1码通过不同的占空比进行区分。然而也出现了一个新问题,常用的STM32F1系列单片机,频率只有72MHz,对于高性能的STMF4系列也不过200MHz左右,也就是说,STM32F1的一个指令周期需要大约14ns,而正常情况下用HAL库控制单片机I/O翻转,至少需要30个指令周期,将近500ns才能实现一次高低电平变化,即使是直接用寄存器驱动I/O,也只能达到12MHz的翻转速度,就是F4系列直接用寄存器驱动,虽然可以超频到240MHz,让I/O翻转速率达到80MHz,然而稳定性也是一个方面。所以,STM32以及所有比他性能还低的单片机,用I/O翻转的方式,是很难驱动WS2812系列灯珠的,除非直接上400M的F7,或者你的片子啥事都不干就驱动一串LED。故此,排除掉直接翻转I/O口的方式,采用PWM+DMA或者SPI+DMA的方式驱动它。本文主讲SPI+DMA的驱动方式。

SPI+DMA的驱动方式

硬件SPI中有一个MOSI引脚来输出数据,我们就是用MOSI的输出功能,通过发送一个字节或半字的数据,来模拟我们的LED控制信号0码或码1,主要就是配置好SPI的时钟即可。看下图: SPI模拟归零码 重点在于SPI的配置上面,我们通过控制SPI的时钟频率可以实现SPI传输8个位的数据使用的时间大致等于1.25us,例如STM32f407的SPI2挂载的APB1总线频率为42Mhz,8分频之后得到的SPI2的SCK的频率为5.25Mhz,周期为0.19us左右,传输8个位的时间为1.5us左右,然后进行一些调整,趋近于1.25us即可。接下来就是一些SPI的具体配置:

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //42M/8=5.xM SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

配置好SPI之后,就是DMA的配置了,为什么采用DMA呢。是因为每次调用SPI发送数据是有时间间隔的,并且会被中断打断,这时候DMA的作用就体现出来了。将DMA的内存地址设置为SIP待发送数据的地址,长度设置为发送数据的大小,然后开启DMA发送,等待DMA发送完成标志位置位即可。下面是DMA的配置部分:

DMA_InitStructure.DMA_Channel = DMA_Channel_0; //通道选择 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR; //DMA外设地址 DMA_InitStructure.DMA_Memory0BaseAddr = (u32)pixelBuffer; //DMA 存储器0地址 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //存储器到外设模式 DMA_InitStructure.DMA_BufferSize = Pixel_S1_NUM * 24; //数据传输量 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度:8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 使用普通模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //中等优先级 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发单次传输 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发单次传输 DMA_Init(DMA1_Stream4, &DMA_InitStructure); //初始化DMA Stream

SPI和DMA的配置就已经结束了,接下来便是数据的转换了。数据转换主要涉及将RGB转换为LED能识别的信号。下图是数据的传输方式: 传输规则 从上面可以看出,24bit的顺序是GRB,这个一定要注意,然后将RGB的颜色转换为对应的24Bit数据即可,RGB转十六进制颜色对照表可以去这儿看:RGB颜色转换 然后就可以了。只需要在点亮某个LED的时候调用具体的函数即可。 后面附上stm32f407通过SPI+DMA方式驱动WS2812的驱动DEMO: https://download.csdn.net/download/cxieyunsky/12248557 ----------------------------------------------------------------------------------------------------------2020/3/14 ----------------------------------------------------------------------------------------------------------@曼珠沙华



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3